package br.com.foxinline.manager.editar;

import br.com.foxinline.modelo.*;
import br.com.foxinline.servico.*;
import br.com.foxinline.util.Conexao;
import br.com.foxinline.util.Msg;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.map.MarkerDragEvent;
import org.primefaces.event.map.PointSelectEvent;
import org.primefaces.event.map.StateChangeEvent;
import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.Marker;
import org.primefaces.model.map.Polygon;
import org.primefaces.model.map.Polyline;

/**
 *
 * @author laverson
 */
@ViewScoped
@ManagedBean
public class ManagerEditarSetor implements Serializable {

    @EJB
    SetorServico setorServico;
    @EJB
    CoordenadaServico coordenadaServico;
    @EJB
    BairroServico bairroServico;
    @EJB
    PrefeituraServico prefeituraServico;
    private Setor setor;
    private DefaultMapModel mapModel;
    private Coordenada coordenada;
    private List<Coordenada> coordenadas;
    private Polygon polygon;
    private String centroMapa;
    private int zoomLevelMapa;
    private String visualizarSetor;
    private String editarSetor;
    private boolean connect;

    @PostConstruct
    public void init() {

        this.centroMapa = prefeituraServico.getCentroMapa();
        this.zoomLevelMapa = prefeituraServico.getZoomMapa();

        this.mapModel = new DefaultMapModel();
        this.polygon = new Polygon();

        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();

        this.visualizarSetor = params.get("visualizarSetor");
        this.editarSetor = params.get("editarSetor");

        String setorId = this.editarSetor != null ? this.editarSetor : this.visualizarSetor;

        paramPost(setorId);

        if (prefeituraServico.find().getDesabilitarMapas()) {

            this.connect = false;
        } else if (!Conexao.isInternetReachable()) {

            this.connect = false;
            Msg.messagemWarn("Não foi possível estabelecer uma conexão com a Internet.");

        } else if (this.coordenadas != null) {
            this.connect = true;
            loadMap();
        }
    }

    public void paramPost(String setorId) {

        try {
            if (setorId != null) {
                this.setor = setorServico.find(Long.parseLong(setorId));
                this.coordenadas = coordenadaServico.find(this.setor);
            }

        } catch (Exception e) {
            System.err.println(e);
        }
    }

    private void loadMap() {
        this.mapModel = new DefaultMapModel();
        LatLng coord;

        if (!this.coordenadas.isEmpty()) {
            Marker mk;

            for (Coordenada c : this.coordenadas) {
                coord = new LatLng(c.getLat(), c.getLog());

                if (this.editarSetor != null) {
                    mk = new Marker(coord, "", c, "");
                    mk.setDraggable(true);
                    this.mapModel.addOverlay(mk);
                }

                this.polygon.getPaths().add(coord);

                this.polygon.setStrokeColor("#FF9900");
                this.polygon.setFillColor("#FF9900");
                this.polygon.setFillOpacity(0);
                this.mapModel.addOverlay(this.polygon);
            }

            this.mapModel.addOverlay(this.polygon);
        }

        mapearBairro(this.mapModel);

        if (this.editarSetor != null) {

            for (Marker premarker : this.mapModel.getMarkers()) {
                premarker.setDraggable(true);
            }
        }
    }

    private void mapearBairro(DefaultMapModel mapModel) {
        Polyline polyline;
        LatLng coord;
        List<Coordenada> bairroCoordenadas;

        for (Bairro bairro : bairroServico.findAll()) {

            bairroCoordenadas = bairroServico.lstCoordenadaBairro(bairro);
            polyline = new Polyline();

            for (Coordenada c : bairroCoordenadas) {
                coord = new LatLng(c.getLat(), c.getLog());

                polyline.getPaths().add(coord);

                polyline.setStrokeColor("#1B93DF");
                polyline.setStrokeWeight(2);
            }

            if (bairroCoordenadas != null && !bairroCoordenadas.isEmpty()) {
                coord = new LatLng(bairroCoordenadas.get(0).getLat(), bairroCoordenadas.get(0).getLog());
                polyline.getPaths().add(coord);
            }

            mapModel.addOverlay(polyline);
        }
    }

    public void handlePointClick(PointSelectEvent event) {
        LatLng latLng = event.getLatLng();

        addOverlayToMapModel(new Marker(latLng, ""));

        this.mapModel.addOverlay(this.polygon);

        for (Marker premarker : this.mapModel.getMarkers()) {
            premarker.setDraggable(true);
        }
    }

    public void onMarkerDrag(MarkerDragEvent event) {
        Marker marker = event.getMarker();

        for (Marker m : this.mapModel.getMarkers()) {
            if (marker.getId().equals(m.getId())) {
                m.setLatlng(marker.getLatlng());
                break;
            }
        }

        this.polygon = new Polygon();
        preencherMapModel();
        mapearBairro(this.mapModel);
    }

    private void preencherMapModel() {
        List<Marker> markers = this.mapModel.getMarkers();
        this.mapModel = new DefaultMapModel();

        for (Marker m : markers) {
            addOverlayToMapModel(m);
        }
        this.mapModel.addOverlay(polygon);

        for (Marker premarker : this.mapModel.getMarkers()) {
            premarker.setDraggable(true);
        }
    }

    public void onStateChange(StateChangeEvent event) {
        this.zoomLevelMapa = event.getZoomLevel();
        this.centroMapa = event.getCenter().getLat() + ", " + event.getCenter().getLng();
    }

    private void addOverlayToMapModel(Marker marker) {
        this.mapModel.addOverlay(marker);

        this.polygon.getPaths().add(marker.getLatlng());
        this.polygon.setStrokeColor("#FF9900");
        this.polygon.setFillColor("#FF9900");
        this.polygon.setFillOpacity(0.2);
    }

    public void removerMarkers() {
        this.mapModel = new DefaultMapModel();
        this.setor.setCoordenadas(new ArrayList<Coordenada>());
        this.polygon = new Polygon();
    }

    public void salvar() {
        try {
            this.coordenadas = new ArrayList<Coordenada>();

            for (Marker marker : this.mapModel.getMarkers()) {
                this.coordenada = new Coordenada();
                this.coordenada.setLat(marker.getLatlng().getLat());
                this.coordenada.setLog(marker.getLatlng().getLng());
                this.coordenadas.add(this.coordenada);
            }

            this.setor.setCoordenadas(this.coordenadas);
            setorServico.update(this.setor);

            this.setor = setorServico.find(this.setor.getId());

            Msg.messagemInfo(Msg.SuccessFull);

        } catch (EJBException e) {

            Exception causedByException = e.getCausedByException();

            if (!(causedByException instanceof javax.validation.ConstraintViolationException)) {
                Msg.messagemError("Já existe um setor com esse número !");
            }

        } catch (Exception e) {

            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    public DefaultMapModel getMapModel() {
        return mapModel;
    }

    public void setMapModel(DefaultMapModel mapModel) {
        this.mapModel = mapModel;
    }

    public Setor getSetor() {
        return setor;
    }

    public void setSetor(Setor setor) {
        this.setor = setor;
    }

    public Coordenada getCoordenada() {
        return coordenada;
    }

    public void setCoordenada(Coordenada coordenada) {
        this.coordenada = coordenada;
    }

    public String getCentroMapa() {
        return centroMapa;
    }

    public void setCentroMapa(String centroMapa) {
        this.centroMapa = centroMapa;
    }

    public int getZoomLevelMapa() {
        return zoomLevelMapa;
    }

    public void setZoomLevelMapa(int zoomLevelMapa) {
        this.zoomLevelMapa = zoomLevelMapa;
    }

    public boolean isConnect() {
        return connect;
    }

    public void setConnect(boolean connect) {
        this.connect = connect;
    }
}
